using System;
using System.Collections.Generic;
using System.Text;
using NBusiness.CodeDom;
using NBusiness.ESharp.Compiler;
using NBusiness.CodeDom.Compiler;

namespace NBusiness.ESharp
{
    [Serializable]
    public class ESharpAccess : EntityAccess
    {
        protected internal override void Attach()
        {
            foreach (EntityElement element in Elements)
            {
                switch (element.Type)
                {
                    case EntityElementType.AccessField:
                        {
                             EntityField[] fields = (Parent as ESharpEntity).Fields.FindAll(new Predicate<EntityField>(
                                delegate(EntityField field)
                                {
                                    return field.Name == element.Value;
                                })).ToArray();

                             if (fields.Length == 0)
                                 OnBuildError(new ESharpBuildError(ESharpErrorCode.ES4000, element));
                             else if (fields.Length > 1)
                                 OnBuildError(new ESharpBuildError(ESharpErrorCode.ES4004, element));
                             else
                                 Field = fields[0];

                            break;
                        }
                }
            }
        }

        protected override void InitializeAssignmentLogic()
        {
            Assignments.Add(new AssignmentLogic(
                ESharpParser.Expressions.DenyAllow,
                EntityElementType.AccessAllow,
                new AssignmentLogicHandler(AssignAllow),
                EntityElementType.AccessDeclaration));

            Assignments.Add(new AssignmentLogic(
                ESharpParser.Expressions.RoleName,
                EntityElementType.AccessRole,
                new AssignmentLogicHandler(AssignRole),
                EntityElementType.AccessAllow));

            Assignments.Add(new AssignmentLogic(
                ESharpParser.Expressions.AccessType,
                EntityElementType.AccessType,
                new AssignmentLogicHandler(AssignType),
                EntityElementType.AccessRole));

            Assignments.Add(new AssignmentLogic(
                ESharpParser.Expressions.Identifier,
                EntityElementType.AccessField,
                EntityElementType.AccessType));

            Assignments.Add(new AssignmentLogic(
                ESharpParser.Expressions.StatementEnd,
                EntityElementType.StatementEnd,
                PostAssignmentAction.Stop,
                EntityElementType.AccessField));
        }

        private void AssignAllow(object sender, AssignmentLogicEventArgs e)
        {
            switch (e.Elements.Peek().Value)
            {
                case "allow":
                    Allow = true;
                    break;
                case "deny":
                    Allow = false;
                    break;
                default:
                    OnBuildError(new ESharpBuildError(ESharpErrorCode.ES4001, e.Elements.Peek()));
                    break;
            }
        }

        private void AssignRole(object sender, AssignmentLogicEventArgs e)
        {
            Role = e.Elements.Peek().Value.Trim('"');
        }

        private void AssignType(object sender, AssignmentLogicEventArgs e)
        {
            switch (e.Elements.Peek().Value)
            {
                case "get":
                    Type = EntityAccessType.Get;
                    break;
                case "set":
                    Type = EntityAccessType.Set;
                    break;
                default:
                    Type = EntityAccessType.Unknown;
                    OnBuildError(new ESharpBuildError(ESharpErrorCode.ES4002, e.Elements.Peek()));
                    break;
            }
        }
    }
}
